/**
 * 事件管理
 */
export default class EventManager {
    private _processMax: number = 10000;    // 队列处理长度
    private _eventHandler: any = {};    // 事件处理
    private _eventQueue: any[] = [];    // 事件队列
    private _addEventList: any[] = [];  // 待添加事件列表

    private static instance: EventManager = new EventManager();
    private constructor () {}

    static getInstance(): EventManager {
        return EventManager.instance;
    }

    /**
     * @description 注册事件
     * @param eventId 
     * @param handler 
     */
    static registerHandler(eventId: string, handler: cc.Component) {
        let eventList: cc.Component[] = this.instance._eventHandler[eventId];
        if (eventList) {
            for (let i =0 ;i<eventList.length;++i) {
                if (eventList[i] == handler) return;
            }
            eventList.push(handler);
        } else {
            eventList = [];
            eventList.push(handler);
            this.instance._eventHandler[eventId] = eventList;
        }
    }

    /**
     * @description 移除事件处理
     * @param eventId 
     * @param handler 
     */
    static removeHandler(eventId: string, handler: cc.Component) {
        let eventList:cc.Component[] = this.instance._eventHandler[eventId];
        if (!eventList) return;

        for (let i = 0; i < eventList.length; ++i) {
            if (eventList[i] == handler) {
                eventList.splice(i, 1);
                if (eventList.length == 0) {
                    delete this.instance._eventHandler[eventId];
                }
                return;
            }
        }
    }

    static removeAllHander() {
        this.instance._eventHandler = {};
    }

    static setProcessMax(max: number) {
        this.instance._processMax = max;
    }

    static pushEvent(event: any) {
        this.instance._addEventList.push(event);
    }

    /**
     * 待添加事件加入队列
     */
    static addEventToQueue() {
        if (this.instance._addEventList.length == 0) return;

        this.instance._addEventList.reduce((queue, curEvent) => {
            queue.push(curEvent);
        }, this.instance._eventQueue);
        this.instance._addEventList = [];
    }

    static processEvent() {
        this.addEventToQueue();

        let index = 0;
        while(this.instance._eventQueue.length > 0) {
            let event = this.instance._eventQueue.shift();
            if (event) {
                const eventId = event['msgId'];
                const eventList = this.instance._eventHandler[eventId];
                if (eventList && eventList.length > 0) {
                    eventList.forEach(e => {
                        if (!e['processEvent']) {
                            cc.warn('need\'processEvent\'function', e);
                        } else {
                            e.processEvent(event);
                        }
                    });
                    event = null;
                } else {
                    this.pushEvent(event);
                }
                index++;
                if (index == this.instance._processMax) {
                    cc.warn('processEvent too max');
                    break;
                }
            }
        }
    }
}